package com.thiswhyme.gateway.sentinel.service.biz;

import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration;
import com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @description: 熔断/限流规则更新处理器抽象类
 * @author: thiswhyme
 * @date: 2021/4/28
 */
@Slf4j
@Service
public abstract class AbstractRuleUpdateHandler implements RuleUpdateHandler {

    @Autowired
    private SentinelProperties sentinelProperties;

    /**
     * 获取规则配置对应的nacos数据源配置key
     * @return
     */
    public abstract String getRuleDatasourceKey();

    /**
     * 根据路由&当前规则生成新规则
     * @param routes
     * @param currentRuleContent
     * @return
     */
    public abstract String genNewRule(List<RouteDefinition> routes, String currentRuleContent);

    @Override
    public void updateRules(List<RouteDefinition> routes) throws NacosException {
        //从nacos获取当前规则
        NacosDataSourceProperties dsNacos = getDegradeNacosDataSourceProperties(getRuleDatasourceKey());
        Properties prop= new Properties();
        prop.setProperty("serverAddr", dsNacos.getServerAddr());
        prop.setProperty("namespace", dsNacos.getNamespace());
        ConfigService configService = NacosFactory.createConfigService(prop);
        String content = configService.getConfig(dsNacos.getDataId(), dsNacos.getGroupId(), 2000);

        //生成新规则
        String configContent = genNewRule(routes, content);

        //更新新规则到nacos
        boolean isPublishOk = configService.publishConfig(dsNacos.getDataId(), dsNacos.getGroupId(), configContent);
        if(isPublishOk) {
            log.info("限流/降级配置更新成功，内容：\n{}", configContent);
        } else {
            log.warn("限流/降级配置更新失败，内容：\n{}", configContent);
        }
    }

    /**
     * 降级配置对应的nacos数据源配置
     * @param datasourceKey 降级配置对应的nacos数据源配置key
     * @return
     */
    private NacosDataSourceProperties getDegradeNacosDataSourceProperties(String datasourceKey) {
        if(StringUtils.isBlank(datasourceKey) || null == sentinelProperties) {
            return null;
        }
        Map<String, DataSourcePropertiesConfiguration> dsMap = sentinelProperties.getDatasource();
        if(CollectionUtils.isEmpty(dsMap)) {
            return null;
        }
        DataSourcePropertiesConfiguration config = sentinelProperties.getDatasource().get(datasourceKey);
        if(null == config) {
            return null;
        }
        return config.getNacos();
    }
}
